package perfume

import (
	"context"
	"fmt"
	"strconv"
	"strings"

	"mall/common/ctxdatax"
	"mall/common/globalkey"
	"mall/common/moneyx"
	"mall/common/resultx"
	"mall/service/backend/common/utils/pointy"
	"mall/service/blog/rpc/blogclient"
	"mall/service/forum/api/internal/svc"
	"mall/service/forum/api/internal/types"
	"mall/service/forum/rpc/forumclient"

	"github.com/sirupsen/logrus"
	"github.com/zeromicro/go-zero/core/logx"
)

type GetPerfumeByIdLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewGetPerfumeByIdLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetPerfumeByIdLogic {
	return &GetPerfumeByIdLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *GetPerfumeByIdLogic) GetPerfumeById(req *types.PerfumeIdReq) (resp *types.KbEntryInfo, err error) {
	if req.Id == nil || *req.Id == 0 {
		return nil, resultx.NewErrCode(resultx.ENTRY_PERFUME_ID_REQUIRED)
	}

	userId := ctxdatax.GetUserId(l.ctx)

	var preload string
	var eagerLoad string
	var with string
	if req.With != nil {
		with = strings.TrimSpace(*req.With)
	}
	var withCollected bool
	if len(with) > 0 {
		switch with {
		case "all":
			preload = "blogBook:Id,Title,Slug,Excerpt;blogMedia:Id,Uid,Url,Thumbnail,Order;blogBookMeta:year,reviewCount,averageRating"
			preload += ",perfumeCount,productCount,minProductGems,backgroundColor,fontColorLight,recommended"
			preload += ";blogBookRelation:brand,nose,group,note,version"
			preload += ";blogBookDetail:ContentHtml"
			eagerLoad = "blogBook:blogMedia,blogBookMeta,blogBookRelation,blogTerm,blogBookDetail"
			withCollected = true
		case "photo":
			preload = "blogBook:Id,Title,Slug;blogMedia:Id,Uid,Url,Thumbnail,Order"
			// blogPhoto是blogMedia的子集，所以指定查询字段的方式依然为blogMedia
			eagerLoad = "blogBook:blogPhoto"
		default:
			preload = "blogBook:Id,Title,Slug;blogMedia:Id,Uid,Url,Thumbnail;blogBookMeta:year;blogBookRelation:" + with
			eagerLoad = "blogBook:blogMedia,blogBookMeta,blogBookRelation,blogTerm"
		}
	}
	var filters []string
	filters = append(filters, "Status,equalTo:"+strconv.FormatInt(int64(globalkey.StatusEnabled), 10))
	var platformId uint32 = globalkey.ThirdPartyPlatformWechatMini
	var searchId int64
	if req.SearchId != nil {
		searchId = *req.SearchId
	}

	detail, err := l.svcCtx.BlogRpc.BookDetail(l.ctx, &blogclient.BookDetailReq{
		Id:          int64(*req.Id),
		Preload:     preload,
		EagerLoad:   eagerLoad,
		VisitorId:   int64(userId),
		PlatformId:  int32(platformId),
		SearchLogId: searchId,
	})
	if err != nil {
		return nil, err
	}

	var collected *bool
	if withCollected {
		var filters []string
		filters = append(filters, "ObjectId,equalTo:"+strconv.FormatInt(int64(*req.Id), 10))
		filters = append(filters, "ObjectType,equalTo:"+strconv.FormatInt(int64(globalkey.PostTypeKnowledgeBase), 10))
		filters = append(filters, "UserId,equalTo:"+strconv.FormatInt(int64(userId), 10))
		res, err := l.svcCtx.ForumRpc.CollectList(l.ctx, &forumclient.CollectListReq{
			Preload:    "forumCollect:Id,UserId,ObjectId,ObjectType",
			Filter:     strings.Join(filters, ";"),
			VisitorId:  int64(userId),
			PlatformId: int32(platformId),
		})
		if err != nil {
			logrus.Info(fmt.Sprintf("GetPerfumeById CollectList err : %+v", err))
		}
		logrus.Info(fmt.Sprintf("GetPerfumeById CollectList res : %+v", res))
		if len(res.Data) > 0 {
			collected = pointy.GetPointer(true)
		}
	}

	var sections []*types.TermInfo
	if len(detail.Sections) > 0 {
		for _, v := range detail.Sections {
			sections = append(sections, &types.TermInfo{
				Id:   pointy.GetPointer(uint64(v.Id)),
				Name: pointy.GetPointer(v.Name),
				Slug: pointy.GetPointer(v.Slug),
			})
		}
	}
	var media []*types.TmpMediaInfo
	if len(detail.Media) > 0 {
		for _, v := range detail.Media {
			media = append(media, &types.TmpMediaInfo{
				Uid:       pointy.GetPointer(uint64(v.Uid)),
				Id:        pointy.GetPointer(strconv.FormatInt(int64(v.Id), 10)),
				Url:       pointy.GetPointer(v.Url),
				Thumbnail: pointy.GetPointer(uint32(v.Thumbnail)),
			})
		}
	}
	var brands []*types.KbEntryInfo
	var perfumes []*types.KbEntryInfo
	var noses []*types.KbEntryInfo
	var groups []*types.KbEntryInfo
	var topNotes []*types.KbEntryInfo
	var heartNotes []*types.KbEntryInfo
	var baseNotes []*types.KbEntryInfo
	var versions []*types.KbEntryInfo
	if len(detail.Relations) > 0 {
		for _, v := range detail.Relations {
			switch v.Section {
			case "brand":
				brands = append(brands, &types.KbEntryInfo{
					Id:    pointy.GetPointer(uint64(v.Id)),
					Title: pointy.GetPointer(v.Title),
					Slug:  pointy.GetPointer(v.Slug),
				})
			case "perfume":
				perfumes = append(perfumes, &types.KbEntryInfo{
					Id:    pointy.GetPointer(uint64(v.Id)),
					Title: pointy.GetPointer(v.Title),
					Slug:  pointy.GetPointer(v.Slug),
				})
			case "noses":
				noses = append(noses, &types.KbEntryInfo{
					Id:    pointy.GetPointer(uint64(v.Id)),
					Title: pointy.GetPointer(v.Title),
					Slug:  pointy.GetPointer(v.Slug),
				})
			case "group":
				groups = append(groups, &types.KbEntryInfo{
					Id:    pointy.GetPointer(uint64(v.Id)),
					Title: pointy.GetPointer(v.Title),
					Slug:  pointy.GetPointer(v.Slug),
				})
			case "note":
				switch int32(v.GroupId) {
				case globalkey.KBEntryTopNote:
					topNotes = append(topNotes, &types.KbEntryInfo{
						Id:    pointy.GetPointer(uint64(v.Id)),
						Title: pointy.GetPointer(v.Title),
						Slug:  pointy.GetPointer(v.Slug),
					})
				case globalkey.KBEntryHeartNote:
					heartNotes = append(heartNotes, &types.KbEntryInfo{
						Id:    pointy.GetPointer(uint64(v.Id)),
						Title: pointy.GetPointer(v.Title),
						Slug:  pointy.GetPointer(v.Slug),
					})
				case globalkey.KBEntryBaseNote:
					baseNotes = append(baseNotes, &types.KbEntryInfo{
						Id:    pointy.GetPointer(uint64(v.Id)),
						Title: pointy.GetPointer(v.Title),
						Slug:  pointy.GetPointer(v.Slug),
					})
				}
			case "version":
				versions = append(versions, &types.KbEntryInfo{
					Id:    pointy.GetPointer(uint64(v.Id)),
					Title: pointy.GetPointer(v.Title),
					Slug:  pointy.GetPointer(v.Slug),
					Url:   pointy.GetPointer(v.Url),
					Year:  pointy.GetPointer(v.Year),
				})
			}
		}
	}
	var year *string
	var reviewCount *uint32
	var averageRating *string
	var recommended *bool
	var perfumeCount *uint32
	var productCount *uint32
	var minProductGems *string
	var backgroundColor *string
	var fontColorLight *bool
	if len(detail.Meta) > 0 {
		for _, v := range detail.Meta {
			switch v.Key {
			case "year":
				year = pointy.GetPointer(v.Value)
			case "reviewCount":
				if i, err := strconv.ParseInt(v.Value, 10, 32); err == nil {
					reviewCount = pointy.GetPointer(uint32(i))
				}
			case "averageRating":
				if f, err := strconv.ParseFloat(v.Value, 64); err == nil {
					averageRating = pointy.GetPointer(moneyx.FormatStar(f, 1))
				}
			case "recommended":
				recommended = pointy.GetPointer(true)
			case "perfumeCount":
				if i, err := strconv.ParseInt(v.Value, 10, 32); err == nil {
					perfumeCount = pointy.GetPointer(uint32(i))
				}
			case "productCount":
				if i, err := strconv.ParseInt(v.Value, 10, 32); err == nil {
					productCount = pointy.GetPointer(uint32(i))
				}
			case "minProductGems":
				minProductGems = pointy.GetPointer(v.Value)
			case "backgroundColor":
				backgroundColor = pointy.GetPointer(v.Value)
			case "fontColorLight":
				fontColorLight = pointy.GetPointer(true)
			}
		}
	}

	return &types.KbEntryInfo{
		Id:              pointy.GetPointer(uint64(detail.Id)),
		Title:           pointy.GetPointer(detail.Title),
		Slug:            pointy.GetPointer(detail.Slug),
		Excerpt:         pointy.GetPointer(detail.Excerpt),
		Content:         pointy.GetPointer(detail.ContentHtml),
		CommentStatus:   pointy.GetPointer(uint32(detail.CommentStatus)),
		CreatedAt:       pointy.GetPointer(detail.Date),
		UpdatedAt:       pointy.GetPointer(detail.Modified),
		Sections:        sections,
		Media:           media,
		Brands:          brands,
		Perfumes:        perfumes,
		Noses:           noses,
		Groups:          groups,
		TopNotes:        topNotes,
		HeartNotes:      heartNotes,
		BaseNotes:       baseNotes,
		Versions:        versions,
		Year:            year,
		AverageRating:   averageRating,
		ReviewCount:     reviewCount,
		Recommended:     recommended,
		PerfumeCount:    perfumeCount,
		ProductCount:    productCount,
		MinProductGems:  minProductGems,
		BackgroundColor: backgroundColor,
		FontColorLight:  fontColorLight,
		Collected:       collected,
	}, nil
}
